'''
this is a project for test ten-flod and leave one
'''
import numpy as np
import matplotlib.pyplot as plt
def input():
    x1=[]
    y1=[]
    x2=[]
    y2=[]
    x3=[]
    y3=[]
    #read data from bezdeklris.data
    with open('bezdekIris.data') as data:
        for line in data:
            x=[]
            inf=line.strip().split(',')
            for attr in inf[0:4]:
                x.append(float(attr))
            if inf[4]=="Iris-setosa":
                x1.append(x)
                y1.append(1)
            elif inf[4]=="Iris-versicolor":
                x2.append(x)
                y2.append(2)
            else:
                x3.append(x)
                y3.append(3)
    return x1,y1,x2,y2,x3,y3
def tenflod(x1,x2):
    '''
    :parameter:x1,x2 is the data
    :return:tenflod_x,tenfold_y are the ten_flod attr and fenlei
    '''
    tenflod_x=[]
    tenfold_y=[]
    for i in range(10):
        flod=[]
        flod+=x1[5*i:5*i+5]
        flod+=x2[5*i:5*i+5]
        tenflod_x.append(flod)
        tenfold_y.append([1]*5+[0]*5)
    return tenflod_x,tenfold_y


def test(weight:np.ndarray,test_data_x:np.ndarray,test_data_y:np.ndarray)->int:
    test_data_x=np.array(test_data_x).reshape((-1,4))
    test_data_y=np.array(test_data_y).reshape((-1,1))
    x_add=np.ones(test_data_x.shape[0]).reshape((-1,1))
    test_data_x=np.concatenate((test_data_x,x_add),axis=1)
    result=np.dot(test_data_x,weight)
    result[result>0]=1
    result[result<0]=0
    num=np.logical_xor(result,test_data_y)
    num=np.logical_not(num).sum()
    print(num)


def ten_flod_ver(x,y):
    for i in range(10):
        train_data_x=x[0:i]+x[i+1:]
        train_data_y=y[0:i]+y[i+1:]
        test_data_x=x[i]
        test_data_y=y[i]
        npx:np.ndarray=np.array(train_data_x).reshape((-1,4))
        npy:np.ndarray=np.array(train_data_y).reshape((-1))
        weight=gradDecend(npx,npy)
        test(weight,test_data_x,test_data_y)




def gradDecend(train_x:np.ndarray,train_y:np.ndarray):
    '''
    :param train_x: N*4
    :param train_y: N
    :return:
    '''
    x_need=np.ones(90)
    train_x=np.concatenate((train_x,x_need[:,np.newaxis]),axis=1)
    weight=np.ones(train_x.shape[1]).reshape((-1,1))*0.1
    line=0.001
    for i in range(15000):
        z=np.dot(train_x,weight)
        t=np.exp(z)/(np.exp(z)+1)
        decend_ori=-np.dot(train_x.T,train_y.reshape((-1,1)))+np.dot(train_x.T,t)
        weight-=line*decend_ori
    return weight


if __name__=="__main__":
    x1,y1,x2,y2,x3,y3=input()
    testx1,testy1=tenflod(x1,x2)
    ten_flod_ver(testx1,testy1)
    testx2,testy2=tenflod(x2,x3)
    testx3,testy3=tenflod(x1,x3)




